package com.example.androidproject.activity;

import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.StrictMode;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.androidproject.R;
import com.example.androidproject.util.FaceSDK;

import java.lang.ref.WeakReference;

public class CameraActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int PICK_IMAGE_ALBUM = 2;
    private static final int REQUEST_PERMISSION = 0x1000;
    private static final int REQUEST_CODE_SELECT_PIC = 120;
    private static final int CROP_PICTURE = 4;
    private HandlerThread handlerThread;
    private FaceHandler faceHandler;
    private static final int MAX_FACE_NUM = 5;//最大可以检测出的人脸数量
    private int realFaceNum = 0;//实际检测出的人脸数量
    private Button mActivityBtnCameraModle;
    private Button mActivityBtnPhotoModle;
    private ImageView mActivityIvModle;
    private LinearLayout mMainActivity;
    private Bitmap bm;//选择的图片的Bitmap对象
    private boolean hasDetected = false;//标记是否检测到人脸
    private Paint paint;//画人脸区域用到的Paint
    private ProgressDialog pd;
    private String selectedImagePath;
    private ImageView mActivityIvExchangeModle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏
        setContentView(R.layout.activity_camera);

        initView();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, REQUEST_PERMISSION);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (faceHandler != null) {
            faceHandler.removeCallbacksAndMessages(null);
        }
        if (handlerThread != null) {
            handlerThread.quit();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_SELECT_PIC && resultCode == Activity.RESULT_OK) {
            if ("file".equals(data.getData().getScheme())) {
                selectedImagePath = data.getData().getPath();
                if (requestCode == 3) {
                    Uri uri = data.getData();
                    cropImage(uri, 500, 500, CROP_PICTURE);
                    mActivityIvModle.setImageURI(uri);
                } else if (requestCode == 2) {
                    if (data != null) {
                        Parcelable extra = data.getParcelableExtra("data");
                        mActivityIvModle.setImageBitmap((Bitmap) extra);
                    }
                }
            } else {

            }

        }
        //获取选择的图片
        Uri selectedImage = data.getData();
        String photoPathFromContentUri = getPhotoPathFromContentUri(this, selectedImage);
        //要使用Android内置的人脸识别，需要将Bitmap对象转为RGB_565格式，否则无法识别
        bm = BitmapFactory.decodeFile(photoPathFromContentUri).copy(Bitmap.Config.RGB_565, true);
        mActivityIvModle.setImageBitmap(bm);
        hasDetected = false;
    }

    public void cropImage(Uri uri, int outputX, int outputY, int requestCode) {
        //裁剪图片意图
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        //裁剪框的比例，1：1
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        //裁剪后输出图片的尺寸大小
        intent.putExtra("outputX", outputX);
        intent.putExtra("outputY", outputY);
        //图片格式
        intent.putExtra("outputFormat", "JPEG");
        intent.putExtra("noFaceDetection", true);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, requestCode);
    }

    public static String getPhotoPathFromContentUri(Context context, Uri uri) {
        String photoPath = "";
        if (context == null || uri == null) {
            return photoPath;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            if (isExternalStorageDocument(uri)) {
                String[] split = docId.split(":");
                if (split.length >= 2) {
                    String type = split[0];
                    if ("primary".equalsIgnoreCase(type)) {
                        photoPath = Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
                }
            } else if (isDownloadsDocument(uri)) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                photoPath = getDataColumn(context, contentUri, null, null);
            } else if (isMediaDocument(uri)) {
                String[] split = docId.split(":");
                if (split.length >= 2) {
                    String type = split[0];
                    Uri contentUris = null;
                    if ("image".equals(type)) {
                        contentUris = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    }
                    String selection = MediaStore.Images.Media._ID + "=?";
                    String[] selectionArgs = new String[]{split[1]};
                    photoPath = getDataColumn(context, contentUris, selection, selectionArgs);
                }
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            photoPath = uri.getPath();
        } else {
            photoPath = getDataColumn(context, uri, null, null);
        }

        return photoPath;
    }

    private static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    private static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    private static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        String column = MediaStore.Images.Media.DATA;
        String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null && !cursor.isClosed()) {
                cursor.close();
            }
        }
        return null;
    }


    private void initView() {
        mActivityBtnCameraModle = (Button) findViewById(R.id.modle_activity_btn_camera);
        mActivityBtnCameraModle.setOnClickListener(this);
        mActivityBtnPhotoModle = (Button) findViewById(R.id.modle_activity_btn_photo);
        mActivityBtnPhotoModle.setOnClickListener(this);
        mActivityIvModle = (ImageView) findViewById(R.id.modle_activity_iv);
        mActivityIvExchangeModle = (ImageView) findViewById(R.id.modle_activity_ivExchange);
        mActivityIvExchangeModle.setOnClickListener(this);
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        paint = new Paint();//创建画笔
        //设置画笔属性
        paint.setColor(Color.BLUE);//画笔颜色为蓝色
        paint.setStrokeWidth(10);//画笔大小
        paint.setStyle(Paint.Style.STROKE);//设置话出的是空心方框而不是实心方块
        pd = new ProgressDialog(this);
        pd.setTitle("提示");
        pd.setMessage("正在检测，请稍等");

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.modle_activity_btn_camera:
                Intent intent = new Intent(CameraActivity.this, FaceDetectorActivity.class);
                startActivity(intent);
                break;
            case R.id.modle_activity_btn_photo:
                openAlbum();
                detectFace();

                break;
            case R.id.modle_activity_ivExchange:// TODO 20/09/02
                break;
            default:
                break;
        }
    }

    private void openAlbum() {
        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, PICK_IMAGE_ALBUM);
    }

    private void detectFace() {
        if (bm == null) {
            Toast.makeText(this, "请先选择图片", Toast.LENGTH_SHORT).show();
            return;
        }
        if (hasDetected) {
            Toast.makeText(this, "已检测出人脸", Toast.LENGTH_SHORT).show();
        } else {
            new FindFaceTask().execute();
        }
    }

    private class FindFaceTask extends AsyncTask<Void, Void, FaceDetector.Face[]> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd.show();
        }

        @Override
        protected FaceDetector.Face[] doInBackground(Void... arg0) {
            //最关键的就是下面三句代码
            FaceDetector faceDetector = new FaceDetector(bm.getWidth(), bm.getHeight(), MAX_FACE_NUM);
            FaceDetector.Face[] faces = new FaceDetector.Face[MAX_FACE_NUM];
            realFaceNum = faceDetector.findFaces(bm, faces);
            if (realFaceNum > 0) {
                return faces;
            }
            return null;
        }

        @Override
        protected void onPostExecute(FaceDetector.Face[] result) {
            super.onPostExecute(result);
            pd.dismiss();
            if (result == null) {
                Toast.makeText(CameraActivity.this, "抱歉，图片中未检测到人脸", Toast.LENGTH_SHORT).show();
            } else {
                drawFacesArea(result);
            }
        }
    }

    private void showResult(final Bitmap bitmap) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mActivityIvModle.setImageBitmap(bitmap);
            }
        });
    }

    private void readGalleryError() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(CameraActivity.this, "Something wrong happened when read gallery.", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private static class FaceHandler extends Handler {
        private WeakReference<CameraActivity> viewWeakReference;

        private WeakReference<Uri> uriWeakReference;

        FaceHandler(Looper looper, CameraActivity activity) {
            super(looper);
            this.viewWeakReference = new WeakReference<>(activity);
        }

        void detect(Uri uri) {
            this.uriWeakReference = new WeakReference<>(uri);
            sendEmptyMessage(0);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            CameraActivity activity = viewWeakReference.get();
            Uri uri = uriWeakReference.get();
            if (activity == null || uri == null) {
                return;
            }
            // get image path from gallery
            String imagePath = getPath(uri, activity.getContentResolver());
            if (imagePath == null) {
                activity.readGalleryError();
                return;
            }
            activity.beginDetect();
            Log.e("tag", " imagePath :" + imagePath);
            // begin detect
            Bitmap bitmap = new FaceSDK().DetectionBitmap(BitmapFactory.decodeFile(imagePath));
            if (viewWeakReference.get() != null) {
                activity.showResult(bitmap);
            }
        }

        private String getPath(Uri uri, ContentResolver provider) {
            String[] projection = {MediaStore.Images.Media.DATA};
            Cursor cursor = provider.query(uri, projection, null, null, null);
            if (cursor == null || !cursor.moveToFirst()) {
                return null;
            }
            int columnIndex = cursor.getColumnIndex(projection[0]);
            String imagePath = cursor.getString(columnIndex);
            cursor.close();
            return imagePath;
        }

    }

    private void beginDetect() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
            }
        });
    }

    private void drawFacesArea(FaceDetector.Face[] faces) {
        Toast.makeText(this, "图片中检测到" + realFaceNum + "张人脸", Toast.LENGTH_SHORT).show();
        float eyesDistance = 0f;//两眼间距
        Canvas canvas = new Canvas(bm);
        for (int i = 0; i < faces.length; i++) {
            FaceDetector.Face face = faces[i];
            if (face != null) {
                PointF pointF = new PointF();
                face.getMidPoint(pointF);//获取人脸中心点
                eyesDistance = face.eyesDistance();//获取人脸两眼的间距
                //画出人脸的区域
                canvas.drawRect(pointF.x - eyesDistance, pointF.y - eyesDistance, pointF.x + eyesDistance, pointF.y + eyesDistance, paint);
                hasDetected = true;
            }
        }
        //画出人脸区域后要刷新ImageView
        mActivityIvModle.invalidate();
    }

}